package api

import (
	"database/sql"
	"fmt"
	"net/http"
	"os"
	"3d-space/internal/database"
	"3d-space/internal/hunyuan"

	"github.com/gin-gonic/gin"
)

type GenerateRequest struct {
	Prompt      string `json:"prompt"`
	ImageBase64 string `json:"image_base64"`
	ImageURL    string `json:"image_url"`
	Name        string `json:"name" binding:"required"`
	Description string `json:"description"`
}

func GenerateModel(c *gin.Context) {
	userID := c.GetInt64("user_id")
	
	// 检查是否有正在生成的模型
	var count int
	err := database.DB.QueryRow(
		"SELECT COUNT(*) FROM models WHERE user_id = ? AND status = 'generating'",
		userID,
	).Scan(&count)
	
	if err == nil && count > 0 {
		c.JSON(http.StatusConflict, gin.H{"error": "您有模型正在生成中，请等待完成后再生成新模型"})
		return
	}
	
	var req GenerateRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	// 从环境变量读取腾讯云密钥
	secretID := os.Getenv("TENCENT_SECRET_ID")
	secretKey := os.Getenv("TENCENT_SECRET_KEY")
	region := os.Getenv("TENCENT_REGION")
	
	if secretID == "" || secretKey == "" {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "服务器未配置腾讯云密钥"})
		return
	}
	
	if region == "" {
		region = "ap-guangzhou"
	}

	// 初始化混元客户端
	client := hunyuan.NewClient(secretID, secretKey, region)

	// 提交任务
	fmt.Printf("[模型生成] 提交任务，用户ID: %d, 模型名称: %s\n", userID, req.Name)
	fmt.Printf("[模型生成] API密钥: %s..., 区域: %s\n", secretID[:10], region)
	
	jobID, err := client.SubmitJob(req.Prompt, req.ImageBase64, req.ImageURL, "GLB", true)
	if err != nil {
		fmt.Printf("[模型生成] 任务提交失败: %v\n", err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "任务提交失败: " + err.Error()})
		return
	}
	
	fmt.Printf("[模型生成] 任务提交成功，JobID: %s\n", jobID)

	// 先创建生成中的记录
	result, err := database.DB.Exec(
		"INSERT INTO models (user_id, name, description, file_format, job_id, status) VALUES (?, ?, ?, ?, ?, ?)",
		userID, req.Name, req.Description, "GLB", jobID, "generating",
	)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "创建记录失败"})
		return
	}
	
	modelID, _ := result.LastInsertId()

	// 异步等待（实际生产环境应使用队列）
	go func() {
		fmt.Printf("[模型生成] 开始等待模型生成，JobID: %s, ModelID: %d\n", jobID, modelID)
		
		files, err := client.WaitForDone(jobID, 4, 600)
		if err != nil {
			// 更新为失败状态
			fmt.Printf("[模型生成] 生成失败，JobID: %s, 错误: %v\n", jobID, err)
			database.DB.Exec(
				"UPDATE models SET status = 'failed' WHERE id = ?",
				modelID,
			)
			return
		}

		fmt.Printf("[模型生成] 生成完成，JobID: %s, 文件数: %d\n", jobID, len(files))

		// 下载 GLB 文件
		fileData, err := hunyuan.DownloadFile(files[0].URL)
		if err != nil {
			fmt.Printf("[模型生成] 下载失败，JobID: %s, 错误: %v\n", jobID, err)
			database.DB.Exec(
				"UPDATE models SET status = 'failed' WHERE id = ?",
				modelID,
			)
			return
		}

		fmt.Printf("[模型生成] 下载成功，JobID: %s, 文件大小: %d bytes\n", jobID, len(fileData))

		// 更新模型数据和状态
		database.DB.Exec(
			"UPDATE models SET file_data = ?, status = 'completed' WHERE id = ?",
			fileData, modelID,
		)
		
		fmt.Printf("[模型生成] 模型保存成功，ModelID: %d\n", modelID)
	}()

	c.JSON(http.StatusAccepted, gin.H{
		"message":  "模型生成中，请稍后查看",
		"job_id":   jobID,
		"model_id": modelID,
	})
}

func ListMyModels(c *gin.Context) {
	userID := c.GetInt64("user_id")

	rows, err := database.DB.Query(`
		SELECT id, name, description, file_format, status, job_id, created_at 
		FROM models WHERE user_id = ? ORDER BY created_at DESC
	`, userID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "查询失败"})
		return
	}
	defer rows.Close()

	models := []gin.H{}
	for rows.Next() {
		var m database.Model
		rows.Scan(&m.ID, &m.Name, &m.Description, &m.FileFormat, &m.Status, &m.JobID, &m.CreatedAt)
		
		modelData := gin.H{
			"id":          m.ID,
			"name":        m.Name,
			"description": m.Description,
			"status":      m.Status,
			"created_at":  m.CreatedAt,
		}
		
		// 只有完成的模型才有文件 URL
		if m.Status == "completed" {
			modelData["file_url"] = fmt.Sprintf("/api/model/%d/file", m.ID)
		}
		
		models = append(models, modelData)
	}

	c.JSON(http.StatusOK, models)
}

func GetModelFile(c *gin.Context) {
	modelID := c.Param("id")

	var fileData []byte
	var fileFormat string
	var status string
	err := database.DB.QueryRow(
		"SELECT file_data, file_format, status FROM models WHERE id = ?",
		modelID,
	).Scan(&fileData, &fileFormat, &status)

	if err == sql.ErrNoRows {
		c.JSON(http.StatusNotFound, gin.H{"error": "模型不存在"})
		return
	}
	
	if status != "completed" {
		c.JSON(http.StatusNotFound, gin.H{"error": "模型尚未生成完成"})
		return
	}

	contentType := "application/octet-stream"
	if fileFormat == "GLB" {
		contentType = "model/gltf-binary"
	}

	c.Data(http.StatusOK, contentType, fileData)
}

// UploadModel 手动上传模型
// UploadModel 手动上传模型
func UploadModel(c *gin.Context) {
	userID := c.GetInt64("user_id")
	
	name := c.PostForm("name")
	description := c.PostForm("description")
	
	if name == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "模型名称不能为空"})
		return
	}
	
	file, err := c.FormFile("file")
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "请上传模型文件"})
		return
	}
	
	// 检查文件格式
	if file.Header.Get("Content-Type") != "model/gltf-binary" && 
	   !hasGLBSuffix(file.Filename) {
		c.JSON(http.StatusBadRequest, gin.H{"error": "仅支持 .glb 格式的模型文件"})
		return
	}
	
	// 读取文件内容
	fileContent, err := file.Open()
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "读取文件失败"})
		return
	}
	defer fileContent.Close()
	
	fileData := make([]byte, file.Size)
	_, err = fileContent.Read(fileData)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "读取文件失败"})
		return
	}
	
	// 存入数据库
	result, err := database.DB.Exec(
		"INSERT INTO models (user_id, name, description, file_data, file_format, status) VALUES (?, ?, ?, ?, ?, ?)",
		userID, name, description, fileData, "GLB", "completed",
	)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "保存失败"})
		return
	}
	
	modelID, _ := result.LastInsertId()
	c.JSON(http.StatusCreated, gin.H{
		"message":  "上传成功",
		"model_id": modelID,
	})
}

func hasGLBSuffix(filename string) bool {
	return len(filename) > 4 && filename[len(filename)-4:] == ".glb"
}

func UpdateModel(c *gin.Context) {
	userID := c.GetInt64("user_id")
	modelID := c.Param("id")

	var req struct {
		Name        string `json:"name"`
		Description string `json:"description"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	result, err := database.DB.Exec(
		"UPDATE models SET name = ?, description = ? WHERE id = ? AND user_id = ?",
		req.Name, req.Description, modelID, userID,
	)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "更新失败"})
		return
	}

	rows, _ := result.RowsAffected()
	if rows == 0 {
		c.JSON(http.StatusNotFound, gin.H{"error": "模型不存在或无权限"})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "更新成功"})
}

func DeleteModel(c *gin.Context) {
	userID := c.GetInt64("user_id")
	modelID := c.Param("id")

	result, err := database.DB.Exec(
		"DELETE FROM models WHERE id = ? AND user_id = ?",
		modelID, userID,
	)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "删除失败"})
		return
	}

	rows, _ := result.RowsAffected()
	if rows == 0 {
		c.JSON(http.StatusNotFound, gin.H{"error": "模型不存在或无权限"})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "删除成功"})
}
